#include "切片_unicode切片.h"
/******************************************************************************
 * 创建一个指定初始容量的 unicode字符切片 动态数组，返回动态数组的地址
 * 初始容量：unicode切片数组 初始化分配空间
 *****************************************************************************/
unicode切片动态数组 创建unicode切片动态数组(int 初始容量) {
    unicode切片动态数组 数组 = {
        .长度 = 0,
        .容量 = 初始容量,
    };
    // 创建数据区
    数组.数据区 = (unicode切片 *)malloc(初始容量*sizeof(unicode切片));
    return 数组;
}
/******************************************************************************
 * 初始化unicode切片的动态数组
 * 切片指针：unicode切片/字符串存储结构
 * 初始容量：unicode切片数组 初始化分配空间
 *****************************************************************************/
void unicode切片动态数组_初始化(unicode切片动态数组 * 数组指针, int 初始容量) {
    if (数组指针 != NULL) {
        数组指针->容量 = 初始容量;
        数组指针->长度 = 0;
        数组指针->数据区 = (unicode切片 *)malloc(初始容量*sizeof(unicode切片));
    }
}
/******************************************************************************
 * 释放unicode切片动态数组的数据区
 * 切片指针：unicode切片/字符串存储结构
 *****************************************************************************/
void unicode切片动态数组_清空(unicode切片动态数组 * 数组指针) {
    if ((数组指针==NULL)||(数组指针->数据区==NULL)) { //保证 切片 数据区数组 存在
        return;
    }
    for (int i=0; i<(数组指针->长度); i++){ // 逐个释放数组元素的数据区
        unicode切片_清空(&(数组指针->数据区[i])); //清空切片数据区
    }
    // 清空整个数据区数组
    free(数组指针->数据区);
    数组指针->数据区 = NULL;
    // 再清空描述块
    数组指针->长度 = 0;
    数组指针->容量 = 0;
}
/******************************************************************************
 * 重置已有切片动态数组到初始化状态
 * 数组指针：unicode切片数组结构体的指针
 *****************************************************************************/
void unicode切片动态数组_重置(unicode切片动态数组 * 数组指针) {
    unicode切片动态数组_清空(数组指针);
    unicode切片动态数组_初始化(数组指针, 8);  //初始分配64元素的空间
}
/******************************************************************************
 * 拓展unicode切片动态数组的容量到足够容纳"期望容量"
 * 切片指针：unicode切片/字符串存储结构
 * 期望容量：切片要达到的最低容量，这里保证分配的容量不小于该值
 *****************************************************************************/
void unicode切片动态数组_扩容(unicode切片动态数组 * 数组指针, int 期望容量) {
    int 新容量 = 数组指针->容量;
    unicode切片 * 新数据区指针;
    while (新容量 < 期望容量) {
        新容量 *= 2;          // 翻倍扩容，直到达到期望容量
    }
    新数据区指针 = realloc(数组指针->数据区, 新容量*sizeof(unicode切片));
    // realloc失败检查
    if (新数据区指针 == NULL) {
        perror("切片扩容内存分配失败！\n");
    }
    // 更新容量和数据区指针
    数组指针->容量 = 新容量;
    数组指针->数据区 = 新数据区指针;
}
/******************************************************************************
 * 追加一个 unicode切片结构体 到切片动态数组中
 * 切片指针：unicode切片/字符串存储结构
 * 待追加字符：需要追加到尾部的unicode字符
 *****************************************************************************/
void unicode切片动态数组_追加(unicode切片动态数组 * 数组指针, unicode切片 待追加切片) {
    // 先检查扩容
    int 新长度 = 数组指针->长度 + 1;
    if (新长度 > 数组指针->容量) { //容量不足，则扩容
        unicode切片动态数组_扩容(数组指针, 新长度);
    }
    // 添加切片结构体，更新长度
    数组指针->数据区[新长度-1] = 待追加切片;
    数组指针->长度 = 新长度;
}
/******************************************************************************
 * 从头遍历动态切片数组元素，返回第一个与目标切片相同的元素的索引，查找失败则返回 -1
 * 数组指针：unicode切片/字符串存储结构
 * 目标切片：需要追加到尾部的unicode字符
 *****************************************************************************/
int unicode切片动态数组_遍历搜索(unicode切片动态数组 被搜索数组, unicode切片 目标切片) {
    //从头开始，遍历所有数组元素
    for (int i=0; i<(被搜索数组.长度); i++) {
        if (unicode切片_判等(被搜索数组.数据区[i], 目标切片)) {
            return i;
        }
    }
    return -1; //未搜索到，返回-1
}
/**********************************************************
 * 以utf8格式打印动态数组，一个元素占一行
 * 数组：unicode切片数组结构体的地址
 * 输出文件：输出的目标文件
 *********************************************************/
void unicode切片动态数组_文件打印(unicode切片动态数组 数组, FILE * 输出文件) {
    for (int i=0; i<数组.长度; i++) {
        unicode切片_文件打印(数组.数据区[i], 输出文件);
    }
}
/**********************************************************
 * 序列化：将整个切片序列化后打印到指定文件，用于调试
 * 数组：unicode切片数组结构体的地址
 * 输出文件：输出的目标文件
 *********************************************************/
void unicode切片动态数组_文件序列化打印(unicode切片动态数组 数组, FILE * 输出文件) {
    // 先打印结构体信息
    fprintf(输出文件, "{%d %d [", 数组.长度, 数组.容量);
    // 再打印数组信息，'"字符串" '
    for (int i=0; i<数组.长度; i++) {
        unicode切片_文件序列化打印(数组.数据区[i], 输出文件);
        fputc(' ', 输出文件);
    }
    if (数组.长度 > 0) {
        fputc('\b', 输出文件); //抹去最后的空格
    }
    fprintf(输出文件, "]}");
}
